package com.ossjk.config.shiro;
//package com.example.shirojwt.shiro;

import java.util.Collection;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.mapper.Condition;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.ossjk.core.util.CommonUtil;
import com.ossjk.core.util.Constant;
import com.ossjk.core.util.JwtTokenUtil;
import com.ossjk.oa.system.entity.Token;
import com.ossjk.oa.system.service.ITokenService;

/**
 * 
 * @author chair
 *
 */

@Component
public class MyRealm extends AuthorizingRealm {

	@Autowired
	private ITokenService iTokenService;
	@Autowired
	private JwtTokenUtil jwtTokenUtil;

	/**
	 * 必须重写此方法，不然Shiro会报错
	 * 
	 * @param token
	 * @return
	 */
	@Override
	public boolean supports(AuthenticationToken token) {
		return token instanceof JwtToken;
	}

	/**
	 * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
	 * 
	 * @param auth
	 * @return
	 * @throws AuthenticationException
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		JwtToken jwtToken = (JwtToken) token;
		String tokenStr = (String) jwtToken.getCredentials();
		// 校验有没有token异常
		if (CommonUtil.isBlank(tokenStr)) {
			throw new NoTokenException("没有token异常");
		}
		// 校验token是否失效
		String uid = jwtTokenUtil.getUserId(tokenStr);
		if (CommonUtil.isBlank(uid)) {
			throw new AuthenticationException("token失效");
		}
		Wrapper wrapper = Condition.create();
		wrapper.eq("token", tokenStr);
		// 查询数据库
		Token tokenObj = iTokenService.selectOne(wrapper);
		if (CommonUtil.isBlank(tokenObj)) {
			// 数据库找不到，为非法
			throw new AuthenticationException("非法token");
		}
		if (jwtTokenUtil.isFlush(tokenStr)) {
			throw new TokenFlushException("token刷新");
		}
		// 获取权限表达式
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		// 拦截通过
		request.setAttribute(Constant.REQUEST_TOKEN_KEY, tokenObj);
		request.setAttribute(Constant.REQUEST_USERID_KEY, tokenObj.getUid());
		String expression = tokenObj.getExpression();
		if(!CommonUtil.isBlank(expression)) {
			Map map = JSON.parseObject(expression, Map.class);

			request.setAttribute(Constant.REQUEST_DID_KEY, map.get(Constant.REQUEST_DID_KEY));
			request.setAttribute(Constant.REQUEST_PID_KEY, map.get(Constant.REQUEST_PID_KEY));
			request.setAttribute(Constant.REQUEST_DSUB_KEY, map.get(Constant.REQUEST_DSUB_KEY));
			request.setAttribute(Constant.REQUEST_PSUB_KEY, map.get(Constant.REQUEST_PSUB_KEY));
			request.setAttribute(Constant.REQUEST_PERSSION_KEY, map.get(Constant.REQUEST_PERSSION_KEY));
		}
		
		
		return new SimpleAuthenticationInfo(tokenStr, tokenStr, getName());
	}

	/**
	 * 只有当需要检测用户权限的时候才会调用此方法，例如checkRole,checkPermission之类的
	 * 
	 * @param principals
	 * @return
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		authorizationInfo.addStringPermissions((Collection<String>) request.getAttribute(Constant.REQUEST_PERSSION_KEY));
		return authorizationInfo;
	}

}
